//    Copyright (C) Kherty.  All rights reserved.
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.Contracts;
using System.IO;
using System.IO.Packaging;
using System.Reflection;
using System.Text;
using System.Xml;
using OpenLS.Core;
using OpenLS.Core.Internals;
using OpenLS.Core.Serialization;
using OpenLS.Drawing.Serialization;

namespace OpenLS.Drawing
{
    public class Theme : IOfficeXmlSerializable, INotifyPropertyChanged
    {
        private FormatScheme _fmtScheme;
        private UndoManager _undoManager;
        private ColorScheme _colorScheme;
        private List<ColorSchemeAndMapping> _extraColorSchemes = new List<ColorSchemeAndMapping>();
        private FontScheme _fontScheme;
        private ObjectStyleDefaults _objectStyleDefaults;

        public List<ColorSchemeAndMapping> ExtraColorSchemes
        {
            get { return _extraColorSchemes; }
        }

        public UndoManager UndoManager
        {
            get { return _undoManager; }
            set { _undoManager = value; }
        }


        public string Name{
            get;
            set;}

        public ColorScheme ColorScheme
        {
            get { return _colorScheme; }
            set
            {
                using (createUndoScope("Color")) //\\loc
                {
                    if (UndoManager != null && UndoManager.IsEnabled)
                    {
                        UndoManager.Add(new SetColorSchemeUndoUnit(this, _colorScheme));
                    }
                    _colorScheme = value;
                    notifyPropertyChanged("ColorScheme");
                }
            }
        }
        UndoUnitScope createUndoScope (string s)
        {
            if (UndoManager == null || !UndoManager.IsEnabled)
                return null;
            return new UndoUnitScope(new CompositeUndoUnit(s), UndoManager);
        }

        public FontScheme FontScheme
        {
            get { return _fontScheme; }
            set
            {
                using (createUndoScope("Font") ) //\\loc
                {
                    if (UndoManager != null && UndoManager.IsEnabled)
                    {
                        UndoManager.Add(new PropertyUndoUnit<FontScheme>(ft => FontScheme = ft, _fontScheme));
                    }
                    _fontScheme = value;
                    notifyPropertyChanged("FontScheme");
                }
            }
        }

        public FormatScheme FormatScheme
        {
            get { return _fmtScheme; }
            set
            {
                _fmtScheme = value;
                notifyPropertyChanged("FormatScheme");
            }
        }


        public ObjectStyleDefaults ObjectStyleDefaults
        {
            get { return _objectStyleDefaults; }
            set { _objectStyleDefaults = value; }
        }


        /* private BaseStyles baseStyles;

        public BaseStyles BaseStyles
        {
            get { return baseStyles; }
            set { baseStyles = value; }
        }*/

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region IOfficeXmlSerializable Members

        public void ReadXml(ReadContext context)
        {
            using (var c = context.Read("theme"))
            {
                Name = c.GetString("name");
                var bs = c.ReadElement<BaseStyles>(); //\\
                ColorScheme = bs.ColorScheme;
                FontScheme = bs.FontScheme;
                FormatScheme = bs.FormatScheme;
                ObjectStyleDefaults = c.ReadOptionalElement<ObjectStyleDefaults>("objectDefaults");
                _extraColorSchemes =
                    c.ReadOptionalListElement<ColorSchemeAndMapping>("extraClrSchemeLst", "extraClrScheme");
                c.WarnIf("custClrLst");
                c.WarnIf("ext");
            }
        }

        public void WriteXml(WriteContext context)
        {
            using (WriteContext c = context.Write("theme"))
            {
                c.SetString("name", Name);
                var bs = new BaseStyles {ColorScheme = ColorScheme, FontScheme = FontScheme, FormatScheme = FormatScheme};
                c.WriteElement(bs);
                c.WriteOptionalElement(ObjectStyleDefaults);
                if (_extraColorSchemes != null)
                {
                    using (WriteContext c2 = c.Write("extraClrSchemeLst"))
                    {
                        foreach (ColorSchemeAndMapping m in ExtraColorSchemes)
                            c2.WriteElement(m);
                    }
                }
                c.WarnIf("custClrLst");
                c.WarnIf("ext");
            }
        }

        #endregion

        public Theme Clone()
        {
            var result = new Theme
                             {
                                 _fontScheme = _fontScheme,
                                 Name = Name,
                                 _objectStyleDefaults = _objectStyleDefaults,
                                 _colorScheme = _colorScheme,
                                 _undoManager = _undoManager,
                                 _fmtScheme = _fmtScheme
                             };
            return result;
        }

        private void notifyPropertyChanged(string propertyName)
        {
            Contract.Requires(GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) != null);
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}